package com.joinway.framework.admin.core.service.file;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;

import com.joinway.framework.admin.core.bean.FileImportContext;
import com.joinway.framework.bean.type.Server;
import com.joinway.framework.extension.groovy.GroovyUtils;

@Service
public class CsvProcessor extends AbstractFileProcessor {

	final static String DELIMITER = ",";
//	final static String ENCODE = "UTF-8";
	final static String ENCODE = "GBK";
	final static byte[] BOM = {(byte)0xEF, (byte)0xBB, (byte)0xBF};
	
	@Override
	public String export(String fileName, Map<String, String> columns, List<?> domains, int port) throws Exception {
		String localfileName = fileName + "." + FileConstants.FileType.Csv;
		
		String url = FileManager.save(FileConstants.FileDir.Download + "/" + UUID.randomUUID().toString(), localfileName, Server.Web, port, new IFileRepository<String>(){
			@Override
			public void save(String file, String context) throws Exception {
				File csv = new File(file);
				
				// add header
				String row = "";
				Iterator<String> columnNames = columns.keySet().iterator();
				while(columnNames.hasNext()){
					String columnName = columnNames.next();
					String title = columns.get(columnName);
					
					row += title + DELIMITER;
//					row += "\"" + title + "\"" + DELIMITER;
				}
				
				// write BOM to make sure excel can open it
//				FileUtils.writeByteArrayToFile(csv, BOM, false);
				
				row = row.substring(0, row.length() - 1);
				FileUtils.write(csv, row, ENCODE, true);
				
				
				// add data
				if(domains != null){
					int columnIndex = 0;
					
					for(Object e : domains){
						columnNames = columns.keySet().iterator();
						row = "";
						
						while(columnNames.hasNext()){
							String columnName = columnNames.next();
							
							Object value = GroovyUtils.getProperty(e, columnName);
							String text = getExportTextValue(columnName, columnIndex, value);
							
							row += text + DELIMITER;
//							row += "\"" + text + "\"" + DELIMITER;
						}
						
						row = row.substring(0, row.length() - 1);
						
//						FileUtils.write(csv, IOUtils.LINE_SEPARATOR_WINDOWS, "UTF-8", true);
						FileUtils.write(csv, IOUtils.LINE_SEPARATOR_WINDOWS, ENCODE, true);
						FileUtils.write(csv, row, ENCODE, true);
//						FileUtils.write(csv, new String(row.getBytes(), ENCODE), true);
						
						columnIndex++;
					}
				}
			}
		});

		
		return url;
	}

//	@Override
//	public FileImportContext imports(File file, String table, String columnMap) throws Exception {
////		List<String> lines = IOUtils.readLines(new BOMInputStream(new FileInputStream(file), false), ENCODE);
//		List<String> lines = IOUtils.readLines(new FileInputStream(file), ENCODE);
////		int count = 0;
//		
//		FileImportContext context = new FileImportContext();
//		
//		if(CollectionUtils.isNotEmpty(lines) && lines.size() > 1){
//			Map<String, String> map = getColumnMap(columnMap);
//			
//			List<String> columns = new ArrayList<>();
//			String[] heads = lines.get(0).split(DELIMITER);
//			
//			String column; 
//			for(int i = 0; i < heads.length; i++){
//				String head = heads[i];
//				
//				if(head.startsWith("'") && head.endsWith("'") || head.startsWith("\"") && head.endsWith("\"")){
//					column = head.substring(1, head.length() - 1);
//				}else{
//					column = head;
//				}
//				
//				columns.add(map.get(column));
//			}
//			
//			List<List<String>> records = new ArrayList<>();
//			int columnCount = columns.size();
//			
//			for(int i = 1; i < lines.size(); i++){
//				List<String> row = new ArrayList<>();
//				String[] data = lines.get(i).split(DELIMITER);
//				
//				for(int j = 0; j < columnCount; j++){
////					String d = data.length > j ? data[j] : ""; 
//					String d = data[j]; 
//					String text = "";
//					if(d.startsWith("'") && d.endsWith("'") || d.startsWith("\"") && d.endsWith("\"")){
////						row.add(d.substring(1, d.length() - 1));
//						text = d.substring(1, d.length() - 1);
//					}else{
////						row.add(d);
//						text = d;
//					}
//					text = getImportTextValue(columns.get(i), i, text);
//					row.add(text);
//				}
//				
//				records.add(row);
//			}
//			
//			context = super.imports(columns, records, table);
//		}else{
//			context = super.createDefaultFileImportContext();
//		}
//		
//		return context;
//	}

	@Override
	public FileImportContext imports(File file, String table, String columnMap) throws Exception {
		FileImportContext context = new FileImportContext();
		
		CSVParser parser = CSVParser.parse(file, java.nio.charset.Charset.forName(ENCODE), CSVFormat.RFC4180);
		List<CSVRecord> csvRecords = parser.getRecords();
		
		if(CollectionUtils.isNotEmpty(csvRecords) && csvRecords.size() > 1){
			Map<String, String> map = getColumnMap(columnMap);
			
			List<String> columns = new ArrayList<>();
			CSVRecord heads = csvRecords.get(0);
			
			String column; 
			for(int i = 0; i < heads.size(); i++){
				String head = heads.get(i);
				column = head;
				columns.add(map.get(column));
			}
			
			List<List<String>> records = new ArrayList<>();
			int columnCount = columns.size();
			
			for(int i = 1; i < csvRecords.size(); i++){
				List<String> row = new ArrayList<>();
				
				CSVRecord data = csvRecords.get(i);
				for(int j = 0; j < columnCount; j++){
					String text = data.get(j);
					text = getImportTextValue(columns.get(j), j, text);
					row.add(text);
				}
				
				records.add(row);
			}
			
			context = super.imports(columns, records, table);
		}else{
			context = super.createDefaultFileImportContext();
		}
		
		return context;
	}
	
	@Override
	public String getFileType() {
		return FileConstants.FileType.Csv;
	}

}



